package com.chatim.nonamechatim.netty;

import com.chatim.nonamechatim.netty.handler.WebSocketHandler;
import com.chatim.nonamechatim.service.UserService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import jakarta.annotation.Resource;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties
public class NettyConfig {

    @Resource
    NettyProperties nettyProperties;

    @Resource
    private UserService userService;

    /**
     * boss 线程池
     * 负责客户端连接
     */
    @Bean
    public NioEventLoopGroup boosGroup(){
        return new NioEventLoopGroup(nettyProperties.getBoss());
    }

    /**
     * worker线程池
     * 负责业务处理
     */
    @Bean
    public NioEventLoopGroup workerGroup(){
        return  new NioEventLoopGroup(nettyProperties.getWorker());
    }
    /**
     * 服务器启动器
     */
    @Bean
    public ServerBootstrap serverBootstrap(){
        ServerBootstrap serverBootstrap  = new ServerBootstrap();
        serverBootstrap
                .group(boosGroup(),workerGroup())   // 指定使用的线程组
                .channel(NioServerSocketChannel.class) // 指定使用的通道
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,nettyProperties.getTimeout()) // 指定连接超时时间
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    // 初始化管道
                    @Override
                    protected void initChannel(SocketChannel socketChannel){
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline
                                //30秒客户端没有向服务器发送心跳则关闭连接
                                .addLast(new IdleStateHandler(30, 0, 0))
                                // 添加http编解码器
                                .addLast(new HttpServerCodec())
                                // 切分大文件
                                .addLast(new ChunkedWriteHandler())
                                // 对http消息做聚合操作，将多个http消息聚合成一个大消息，这里传入了一个最大消息长度
                                .addLast(new HttpObjectAggregator(1024 * 64))
                                // webSocket协议处理，负责webSocket协议连接以及控制帧
                                .addLast(new WebSocketServerProtocolHandler("/"))
                                // 自定义webSocket处理器
                                .addLast(new WebSocketHandler(userService));
                    }
                }); // 指定worker处理器
        return serverBootstrap;
    }

}
